using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace DrivingGame
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Camera : Microsoft.Xna.Framework.GameComponent
    {
        public static BoundingBox[] buildingBoundingBoxes;
        //Camera matrices
        public Matrix view { get; protected set; }
        public Matrix projection { get; protected set; }

        // Camera vectors
        public Vector3 position { get; protected set; }
        private Quaternion cameraRotation;
        private float lerpAmount = 1.0f;
        private BoundingSphere cameraSphere;


        public Camera(Game game, Vector3 carPostion, Quaternion carRotation)
            : base(game)
        {
            cameraRotation = Quaternion.Identity;

            CreateLookAt(carPostion, carRotation);

            projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.PiOver4,
                (float)Game.Window.ClientBounds.Width /
                (float)Game.Window.ClientBounds.Height,
                1.0f, 1000.0f);
        }

        public void CreateLookAt(Vector3 carPostion, Quaternion carRotation)
        {
            cameraRotation = Quaternion.Lerp(cameraRotation, carRotation, lerpAmount);
            Vector3 cameraPosition = new Vector3(0f, 6.0f, -14.0f);
            cameraPosition = Vector3.Transform(cameraPosition, Matrix.CreateFromQuaternion(cameraRotation));
            cameraPosition += carPostion;

            Vector3 cameraUp = new Vector3(0.0f, 1.0f, 0.0f);
            cameraUp = Vector3.Transform(cameraUp, Matrix.CreateFromQuaternion(cameraRotation));

            Vector3 cameraTarget = new Vector3(0f, 5.0f, 0f);
            cameraTarget = Vector3.Transform(cameraTarget, Matrix.CreateFromQuaternion(cameraRotation));
            cameraTarget += carPostion;

            // make sure camera will not be in the building
            cameraSphere = new BoundingSphere(cameraPosition, 1.0f);
            if (CollidesWithBuildings(cameraSphere))
            {
                cameraPosition = carPostion + new Vector3(0f, 20.0f, 0.0f);
                cameraTarget = carPostion;
                cameraUp = Vector3.UnitZ;
            }

            this.position = cameraPosition;

            view = Matrix.CreateLookAt(cameraPosition,
                cameraTarget, cameraUp);
        }

        public bool CollidesWithBuildings(BoundingSphere boundingSphere)
        {
            for (int i = 0; i < buildingBoundingBoxes.Length; i++)
                if (buildingBoundingBoxes[i].Contains(boundingSphere) == ContainmentType.Intersects || buildingBoundingBoxes[i].Contains(boundingSphere) == ContainmentType.Contains)
                    return true;
            return false;
        }
    }
}
